package net.cyndeline.temporary

import javafx.application.Application
import javafx.stage.Stage
import javafx.scene.{Group, Scene}
import javafx.scene.canvas.Canvas
import net.cyndeline.scalarlib.entityComponent.miranda.entityManager.EntityManager
import net.cyndeline.scalarlib.entityComponent.miranda.{EntityComponentManager, Entity}
import net.cyndeline.entityComponent.components.gameMap.PositionComponent
import net.cyndeline.entityComponent.components.gui.GraphicsComponent
import net.cyndeline.GUI.setup.{Dungeon_floor, Dungeon_wall}
import net.cyndeline.GUI.canvas.Renderer2D
import akka.actor.{Props, ActorSystem}
import net.cyndeline.GUI.actors.{RepresentationParser, RenderManager}
import net.cyndeline.GUI.rendering.GraphicsContainer
import net.cyndeline.gameMap.{GridMap, Grid}
import net.cyndeline.GUI.actors.messages.{RenderMap, MapToParse}


object TestMapLauncher {
  def main(args: Array[String]): Unit = {
    ActorRefs.fff
    //Application.launch(classOf[TestMapLauncher], args: _*)
  }

}

class TestMapLauncher extends Application {
  def start(primary: Stage) {
    println("Helooo world")

    primary.setTitle("A map")
    val group = new Group()
    val canvas = new Canvas()
    group.getChildren.add(canvas)
    val canvasWidth = 400
    val canvasHeight = 300
    val scene = new Scene(group, canvasWidth, canvasHeight)

    primary.setScene(scene)
    primary.show()

    val entitySystem = new EntityManager()

    val tileWidth = 32
    val tileHeight = 32

    // Graphics
    val renderer = new Renderer2D(canvas.getGraphicsContext2D)
    val graphics = new GraphicsContainer()

    // Map
    val map = MapCreator.create(10, 11, entitySystem)

    // Actor messages
    val parseMsg = MapToParse(entitySystem, graphics, map, tileWidth, tileHeight)
    val renderMsg = RenderMap(entitySystem, List(renderer), graphics, map, map.tile(3, 4).environment.get, canvasWidth, canvasHeight)

//    ActorRefs.renderManager ! renderMsg
//    ActorRefs.renderParser ! parseMsg

  }
}

// Static references, Akka doesn't play nice inside JavaFX apps when setting up systems or actors.
object ActorRefs {
  val system = ActorSystem("myBeatifulSystem")
  val renderManager = ActorRefs.system.actorOf(Props[RenderManager], "Render manager")
  val renderParser = ActorRefs.system.actorOf(Props[RepresentationParser], "Render parser")

  def fff {
    renderParser ! "Hello"
  }

}

object EntityCreator {


  def createWall(x: Int, y: Int, manager: EntityComponentManager): Entity = {
    val graphicsType = manager.componentType(classOf[GraphicsComponent])
    val e = createEnvironment(x, y, manager)
    manager.getComponent(e, graphicsType).graphicsId = Dungeon_wall
    e
  }

  def createFloor(x: Int, y: Int, manager: EntityComponentManager): Entity = {
    val graphicsType = manager.componentType(classOf[GraphicsComponent])
    val e = createEnvironment(x, y, manager)
    manager.getComponent(e, graphicsType).graphicsId = Dungeon_floor
    e
  }

  private def createEnvironment(x: Int, y: Int, manager: EntityComponentManager): Entity = {
    val positionType = manager.componentType(classOf[PositionComponent])
    val graphicsType = manager.componentType(classOf[GraphicsComponent])
    val e = manager.createEntity
    val posComp = manager.addComponent(e, positionType)
    manager.addComponent(e, graphicsType)
    posComp.x = x
    posComp.y = y
    e
  }
}

object MapCreator {

  def create(width: Int, height: Int, manager: EntityComponentManager): Grid = {
    val map = new GridMap(width, height)
    for (i <- 0 until map.width; j <- 0 until map.height) {
      if (i == 0 || j == 0 || i == map.width - 1 || j == map.height - 1) {
        map.tile(i, j).environment = Option(EntityCreator.createWall(i, j, manager))
      } else {
        map.tile(i, j).environment = Option(EntityCreator.createFloor(i, j, manager))
      }
    }
    map
  }
}
